package com.wql.crypto;

import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import com.wql.crypto.common.HexUtils;

public class PBEUtils {
	private PBEUtils() {
	}

	public static final String ALGORITHM = "PBEWITHMD5andDES";

	public static final String CHARSET_NAME = "utf-8";

	public static final int ITERATION_COUNT = 100;

	/**
	 * 初始化盐
	 * 
	 * @return
	 */
	public static String initSalt() {
		SecureRandom random = new SecureRandom();
		return HexUtils.byte2HexStr(random.generateSeed(8));
	}

	/**
	 * 加密
	 * 
	 * @param data
	 * @param password
	 * @param salt
	 * @return
	 */
	public static String encrypt(String data, String password, String salt) {
		try {
			Key key = toKey(password);
			PBEParameterSpec param = new PBEParameterSpec(HexUtils.hexStr2byte(salt), ITERATION_COUNT);
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			cipher.init(Cipher.ENCRYPT_MODE, key, param);
			return HexUtils.byte2HexStr(cipher.doFinal(data.getBytes(CHARSET_NAME)));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密
	 * 
	 * @param data
	 * @param password
	 * @param salt
	 * @return
	 */
	public static String decrypt(String data, String password, String salt) {
		try {
			Key key = toKey(password);
			PBEParameterSpec param = new PBEParameterSpec(HexUtils.hexStr2byte(salt), ITERATION_COUNT);
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			cipher.init(Cipher.DECRYPT_MODE, key, param);
			return new String(cipher.doFinal(HexUtils.hexStr2byte(data)), CHARSET_NAME);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	// 转换密钥
	private static Key toKey(String password) {
		try {
			PBEKeySpec key = new PBEKeySpec(password.toCharArray());
			SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
			return factory.generateSecret(key);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) {
		String str = "hello world!", pwd = "this is password";
		String salt = initSalt();
		System.out.println("str=" + str);
		System.out.println("pwd=" + pwd);
		System.out.println("salt=" + salt);
		System.out.println("encrypt=" + encrypt(str, pwd, salt));
		System.out.println("decrypt=" + decrypt(encrypt(str, pwd, salt), pwd, salt));

	}
}
